#include <algorithm>
#include <iostream>
#include <limits>
#include <set>
#include <vector>
#include <tuple>
#include <unordered_map>

using namespace std;

static const long long INF_TIME = numeric_limits<long long>::max();
static const int MAX_SPLITS = 4;

struct Block {
  int id;
  long long addr;
  long long size;
  long long start_time;
  long long duration;
};

struct AtomicInterval {
  int id;
  long long start;
  long long end;
  long long size;
  vector<pair<long long, int>> uses;  // (start_time, group_index)
  
  long long loaded_len = 0;
  int next_use_cursor = 0;
  long long cached_next_use = INF_TIME;
  int split_count = 0;

  int get_next_use_group() const {
    if (next_use_cursor < (int)uses.size()) return uses[next_use_cursor].second;
    return -1;
  }

  void update_cache() {
    cached_next_use = (next_use_cursor < (int)uses.size()) 
                      ? uses[next_use_cursor].first : INF_TIME;
  }
};

struct Group {
  int id;
  long long start_time;
  long long duration;
  vector<int> block_indices;
  vector<int> interval_indices;
};

class BeladyScheduler {
private:
  int L, M, N;
  vector<Block> blocks;
  vector<AtomicInterval> intervals;
  vector<tuple<string, long long, long long, long long>> events;
  
  long long loaded_size = 0;
  long long io_finish_time = 0;
  long long compute_finish_time = 0;
  
  set<int> loaded_indices;
  vector<Group> groups;
  vector<long long> group_finish_times;
  vector<long long> group_duration_prefix;
  
  // block -> intervals 映射（预计算）
  vector<vector<int>> block_to_intervals;

  void build_atomic_intervals() {
    // 收集所有坐标点
    vector<long long> coords;
    coords.reserve(2 * N + 2);
    coords.push_back(0);
    coords.push_back(L);
    for (const auto &b : blocks) {
      coords.push_back(b.addr);
      coords.push_back(b.addr + b.size);
    }
    sort(coords.begin(), coords.end());
    coords.erase(unique(coords.begin(), coords.end()), coords.end());

    // 创建 intervals
    intervals.reserve(coords.size());
    for (size_t i = 0; i + 1 < coords.size(); ++i) {
      if (coords[i] < coords[i + 1]) {
        AtomicInterval iv;
        iv.id = (int)intervals.size();
        iv.start = coords[i];
        iv.end = coords[i + 1];
        iv.size = iv.end - iv.start;
        intervals.push_back(iv);
      }
    }

    // 构建 interval_starts 用于二分查找
    vector<long long> interval_starts(intervals.size());
    for (size_t i = 0; i < intervals.size(); ++i) {
      interval_starts[i] = intervals[i].start;
    }

    // 直接用二分查找构建 block -> intervals 映射
    // 对每个 block，找到覆盖的 interval 范围
    block_to_intervals.resize(N);
    for (int i = 0; i < N; ++i) {
      long long b_start = blocks[i].addr;
      long long b_end = blocks[i].addr + blocks[i].size;
      
      // 二分找第一个 interval.start >= b_start 的位置
      int lo = 0, hi = (int)intervals.size();
      while (lo < hi) {
        int mid = (lo + hi) / 2;
        if (intervals[mid].end <= b_start) lo = mid + 1;
        else hi = mid;
      }
      
      // 从 lo 开始遍历，直到 interval.start >= b_end
      for (int k = lo; k < (int)intervals.size() && intervals[k].start < b_end; ++k) {
        block_to_intervals[i].push_back(k);
      }
    }

    // 为每个 interval 构建 uses 列表
    for (int i = 0; i < N; ++i) {
      for (int iv_idx : block_to_intervals[i]) {
        auto &iv = intervals[iv_idx];
        if (iv.uses.empty() || iv.uses.back().first != blocks[i].start_time) {
          iv.uses.push_back({blocks[i].start_time, -1});
        }
      }
    }

    for (auto &iv : intervals) {
      iv.update_cache();
    }
  }

  void build_groups() {
    if (N == 0) return;
    
    long long last_start = -1;
    for (int i = 0; i < N; ++i) {
      if (i == 0 || blocks[i].start_time != last_start) {
        Group g;
        g.id = (int)groups.size();
        g.start_time = blocks[i].start_time;
        g.duration = blocks[i].duration;
        groups.push_back(g);
        last_start = blocks[i].start_time;
      }
      groups.back().block_indices.push_back(i);
    }

    // 构建 duration 前缀和
    group_duration_prefix.resize(groups.size() + 1, 0);
    for (size_t i = 0; i < groups.size(); ++i) {
      group_duration_prefix[i + 1] = group_duration_prefix[i] + groups[i].duration;
    }

    // 构建 start_time -> group_id 映射
    unordered_map<long long, int> start_to_group;
    for (auto &g : groups) {
      start_to_group[g.start_time] = g.id;
    }

    // 先更新所有 uses 中的 group_index（一次遍历）
    for (auto &iv : intervals) {
      for (auto &u : iv.uses) {
        auto it = start_to_group.find(u.first);
        if (it != start_to_group.end()) {
          u.second = it->second;
        }
      }
    }

    // 使用预计算的 block_to_intervals 构建 group.interval_indices
    for (auto &g : groups) {
      vector<int> used_ivs;
      for (int b_idx : g.block_indices) {
        for (int iv_idx : block_to_intervals[b_idx]) {
          used_ivs.push_back(iv_idx);
        }
      }
      sort(used_ivs.begin(), used_ivs.end());
      used_ivs.erase(unique(used_ivs.begin(), used_ivs.end()), used_ivs.end());
      g.interval_indices = move(used_ivs);
    }
  }

  double calc_eviction_score(int idx, int current_g_idx) {
    auto &iv = intervals[idx];
    if (iv.loaded_len <= 0) return -1e18;
    
    int next_use_g = iv.get_next_use_group();
    if (next_use_g < 0) return 1e18 + iv.loaded_len;
    
    long long len = iv.loaded_len;
    long long total_io_cost = len * 80;
    
    long long available_compute = 0;
    if (next_use_g > current_g_idx && next_use_g <= (int)groups.size()) {
      available_compute = group_duration_prefix[next_use_g] - group_duration_prefix[current_g_idx];
    }
    
    long long effective_cost = max(0LL, total_io_cost - available_compute);
    int distance = max(1, next_use_g - current_g_idx);
    
    return (double)distance * 10000.0 - (double)effective_cost / (double)max(1LL, len);
  }

  void perform_offload(long long target, const vector<bool> &locked, int g_idx) {
    if (target <= 0) return;

    vector<pair<double, int>> cands;
    cands.reserve(loaded_indices.size());
    for (int idx : loaded_indices) {
      if (intervals[idx].loaded_len > 0 && !locked[idx]) {
        cands.push_back({calc_eviction_score(idx, g_idx), idx});
      }
    }
    if (cands.empty()) return;

    sort(cands.begin(), cands.end(), greater<pair<double, int>>());

    long long freed = 0;
    vector<pair<int, long long>> victims;

    for (auto &[score, idx] : cands) {
      if (freed >= target) break;
      auto &iv = intervals[idx];
      
      long long amount = min(iv.loaded_len, target - freed);
      bool can_partial = (iv.split_count < MAX_SPLITS);
      
      if (can_partial && N >= 50 && iv.size > 4) {
        long long min_chunk = max(1LL, iv.size / 4);
        amount = max(amount, min_chunk);
        amount = min(amount, iv.loaded_len);
        if (amount < iv.loaded_len) iv.split_count++;
      } else if (!can_partial) {
        amount = iv.loaded_len;
      }

      victims.push_back({idx, amount});
      iv.loaded_len -= amount;
      loaded_size -= amount;
      freed += amount;
      if (iv.loaded_len == 0) loaded_indices.erase(idx);
    }

    if (victims.empty()) return;

    // 合并相邻 offload
    sort(victims.begin(), victims.end(), [&](auto &a, auto &b) {
      return intervals[a.first].start < intervals[b.first].start;
    });

    struct Op { long long safe, start, end; };
    vector<Op> ops;

    for (auto &[idx, amount] : victims) {
      auto &iv = intervals[idx];
      long long safe = io_finish_time;
      if (iv.next_use_cursor > 0) {
        int last_g = iv.uses[iv.next_use_cursor - 1].second;
        if (last_g >= 0 && last_g < g_idx) {
          safe = max(safe, group_finish_times[last_g]);
        }
      }

      long long old_len = iv.loaded_len + amount;
      long long p_start = iv.start + (iv.size - old_len);
      long long p_end = iv.start + (iv.size - iv.loaded_len);

      if (!ops.empty() && ops.back().end == p_start && ops.back().safe == safe) {
        ops.back().end = p_end;
      } else {
        ops.push_back({safe, p_start, p_end});
      }
    }

    sort(ops.begin(), ops.end(), [](auto &a, auto &b) { return a.safe < b.safe; });

    for (auto &op : ops) {
      long long actual = max(op.safe, io_finish_time);
      long long sz = op.end - op.start;
      if (sz <= 0) continue;
      events.emplace_back("Offload", actual, op.start, sz);
      io_finish_time = actual + sz * 40;
    }
  }

  void perform_reload(const vector<int> &missing) {
    vector<int> sorted = missing;
    sort(sorted.begin(), sorted.end(), [&](int a, int b) {
      return intervals[a].start < intervals[b].start;
    });

    vector<pair<long long, long long>> loads;
    for (int idx : sorted) {
      long long needed = intervals[idx].size - intervals[idx].loaded_len;
      if (needed <= 0) continue;

      long long s = intervals[idx].start;
      long long e = s + needed;

      if (loads.empty() || loads.back().second != s) {
        loads.push_back({s, e});
      } else {
        loads.back().second = e;
      }

      intervals[idx].loaded_len = intervals[idx].size;
      loaded_size += needed;
      loaded_indices.insert(idx);
    }

    for (auto &[s, e] : loads) {
      long long sz = e - s;
      events.emplace_back("Reload", io_finish_time, s, sz);
      io_finish_time += sz * 40;
    }
  }

  void process_group(int g_idx) {
    const auto &group = groups[g_idx];
    
    vector<int> missing;
    long long needed = 0;
    vector<bool> locked(intervals.size(), false);

    for (int iv_idx : group.interval_indices) {
      locked[iv_idx] = true;
      auto &iv = intervals[iv_idx];
      
      if (iv.loaded_len < iv.size) {
        missing.push_back(iv_idx);
        needed += (iv.size - iv.loaded_len);
      }
      
      while (iv.next_use_cursor < (int)iv.uses.size() &&
             iv.uses[iv.next_use_cursor].second <= g_idx) {
        iv.next_use_cursor++;
      }
      iv.update_cache();
    }

    if (loaded_size + needed > M) {
      perform_offload(loaded_size + needed - M, locked, g_idx);
    }

    if (!missing.empty()) {
      perform_reload(missing);
    }

    long long actual = max({compute_finish_time, io_finish_time, group.start_time});
    for (int b_idx : group.block_indices) {
      events.emplace_back("Visit", actual, blocks[b_idx].id, -1);
    }

    compute_finish_time = actual + group.duration;
    group_finish_times[g_idx] = compute_finish_time;
  }

  void try_prefetch(int g_curr, int g_next) {
    const auto &next_group = groups[g_next];
    
    vector<int> cands;
    for (int idx : next_group.interval_indices) {
      if (intervals[idx].loaded_len < intervals[idx].size) {
        cands.push_back(idx);
      }
    }
    if (cands.empty()) return;

    sort(cands.begin(), cands.end(), [&](int a, int b) {
      return intervals[a].start < intervals[b].start;
    });

    // 只预取有空间的部分，不做驱逐
    for (int idx : cands) {
      long long need = intervals[idx].size - intervals[idx].loaded_len;
      if (need <= 0) continue;
      
      if (loaded_size + need <= M) {
        intervals[idx].loaded_len = intervals[idx].size;
        loaded_size += need;
        loaded_indices.insert(idx);
        events.emplace_back("Reload", io_finish_time, intervals[idx].start, need);
        io_finish_time += need * 40;
      }
    }
  }

public:
  BeladyScheduler(int l, int m, int n) : L(l), M(m), N(n) {}

  void add(int addr, int size, int start, int dur, int id) {
    blocks.push_back({id, addr, size, start, dur});
  }

  void solve() {
    sort(blocks.begin(), blocks.end(), [](const Block &a, const Block &b) {
      return a.start_time < b.start_time;
    });

    build_atomic_intervals();
    build_groups();
    group_finish_times.resize(groups.size(), 0);

    for (int g = 0; g < (int)groups.size(); ++g) {
      process_group(g);
      if (g + 1 < (int)groups.size()) {
        try_prefetch(g, g + 1);
      }
    }

    events.emplace_back("Fin", max(io_finish_time, compute_finish_time), 0, -1);
  }

  void output() {
    sort(events.begin(), events.end(), [](const auto &a, const auto &b) {
      if (get<1>(a) != get<1>(b)) return get<1>(a) < get<1>(b);
      return get<0>(a) < get<0>(b);
    });

    for (const auto &e : events) {
      const string &type = get<0>(e);
      long long time = get<1>(e);
      long long arg1 = get<2>(e);
      long long arg2 = get<3>(e);

      if (type == "Fin") cout << "Fin " << time << "\n";
      else if (type == "Visit") cout << "Visit " << time << " " << arg1 << "\n";
      else cout << type << " " << time << " " << arg1 << " " << arg2 << "\n";
    }
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int L, M, N;
  if (!(cin >> L >> M >> N)) return 0;

  BeladyScheduler sched(L, M, N);
  for (int i = 0; i < N; i++) {
    int addr, size, start, dur;
    cin >> addr >> size >> start >> dur;
    sched.add(addr, size, start, dur, i);
  }

  sched.solve();
  sched.output();
  return 0;
}
